/*
 * TODO
 * inheritance here!
 */

dcat_instance.oninit(function(Y) {
  
  Cat.layout = {}


  // ---  layout -------------------------------------------------------------
  Cat.layout.Layout = function(el) {
    if (el) {
      this.el = el;
      console.log('this_el is ', this.el);
      el.cat_layout = this;
      this.setupDroppable();
      ch = Y.get(this.el).get('children');
      if (ch.length > 0) {
        ch.each(function(e) {
          this.el.cat_layout.apply(e);
        });
      }
    }
    this.publish('layout:afterAppendChild', {emitFacade: false});
    this.publish('layout:appendChild', {emitFacade: false});
    this.publish('layout:removeChild', {emitFacade: false});
    /**/
  }

  Y.augment(Cat.layout.Layout, Y.Event.Target);

  Cat.layout.Layout.prototype.setupDroppable = function() {
    console.log('this_el is ', this.el);
    var drop = new Y.DD.Drop({ node: this.el });
    drop.on('drop:hit', this.drop, this);
  }

  Cat.layout.Layout.prototype.apply = function(el) {
  }

  Cat.layout.Layout.prototype.drop = function() {
  }

  Cat.layout.Layout.prototype.appendChild = function(on, ev) {
  }

  Cat.layout.Layout.prototype.removeChild = function(child) {
    console.log('WILL FIREEE layout:removeChild!')
    this.fire('layout:removeChild', [child]);
  }


  // --- horizontal ------------------------------------------------------------
  Cat.layout.Horizontal = function(el) {
    Cat.layout.Horizontal.superclass.constructor.call(this, el);
  }

  Y.extend(Cat.layout.Horizontal, Cat.layout.Layout);

  Cat.layout.Horizontal.prototype.apply = function(el) {
    el.setStyle('top', '0');
    el.setStyle('left', '0');
    el.setStyle('position', 'relative');
    el.setStyle('display', 'block');
  }

  Cat.layout.Horizontal.prototype.drop = function(on, ev) {
    el = ev.drag.get('node');
    var old_parent = el.get('parentNode');
    var new_parent = on.get('node');
    try {
      new_parent.appendChild(el);
      // shake the parent so google chrome displays the sizes well
      //new_parent.get('parentNode').appendChild(new_parent);
      if (old_parent.layout) {
        old_parent.layout.removeChild(el);
      }
    } catch (err) {
      //////console.log(err);
      old_parent.appendChild(el);
    }

    this.apply(el);
  }


  // --- vertical --------------------------------------------------------------

  Cat.layout.Vertical = function(el) {
    Cat.layout.Vertical.superclass.constructor.call(this, el);
  }

  Y.extend(Cat.layout.Vertical, Cat.layout.Layout);

  Cat.layout.Vertical.prototype.apply = function(el) {
    console.log('vertical apply');
    el.setStyle('top', '0');
    el.setStyle('left', '0');
    el.setStyle('position', 'relative');
    el.setStyle('display', 'block');
    //el.setStyle('float', 'none');
  }

  Cat.layout.Vertical.prototype.drop = function(ev) {
    console.log('vertical layout event', ev);
    el = ev.drag.get('node');
    var old_parent = el.get('parentNode');
    var new_parent = ev.target.get('node');
    console.log('target', ev.target.get('node'));
    console.log('currentTarget', ev.currentTarget.get('node'));
    console.log('drop', ev.drop.get('node'));
    console.log('this.el', this.el);


    posY = el.getY();
    //console.log(posY);

    console.log('layout:appendChild', [el]);
    if (!this.fire('layout:appendChild', [el])) {
      return true;
    }

    try {
      var children = new_parent.get('childNodes');
      //console.log(children);
      var smallest_delta = 10000;
      var swap_with = null;
      var order = 0;

      // tady to nejak pozlobilo kdyz jsem byl v
      // http://localhost/page a dynamicky vytvarel (mozna spatne) page
      if (children) {
        children.each(function(child) {
          var delta = posY - child.getY();
          child.order = order;
          order += 1;
          if (Math.abs(smallest_delta) > Math.abs(delta) && child != el) {
            smallest_delta = delta;
            swap_with = child;
          }
        });
        
        if (swap_with != null) {
          if (swap_with == el.next()) {
            //console.log('A');
            // IE doesnt cooperate here
            insert_after = (Math.abs(smallest_delta) - swap_with.get('clientHeight')/2 <= el.get('clientHeight') /2 );
          } else if(swap_with.next() == el ) {
            //console.log('B');
            insert_after = !(smallest_delta < (el.get('clientHeight')/2))
          } else if (swap_with.next() == null) {
            //console.log('C');
            insert_after = true;//smallest_delta > (el.get('clientHeight')/2);
          } else if (swap_with != el.next()) {
            //console.log('D');
            insert_after = swap_with.order > el.order;
          }

          if (insert_after) {
            new_parent.insertBefore(el, swap_with);
            new_parent.insertBefore(swap_with, el);
          } else {
            new_parent.insertBefore(el, swap_with);
          }
        }

      } else {
        new_parent.appendChild(el);
      }
      var insert_after = null;

      this.apply(el);

      if (old_parent != new_parent) {
        this.fire('layout:afterAppendChild', [el]);
        if (old_parent.layout) {
          old_parent.layout.removeChild(el)
        }
        ev.halt();
      }      
    } catch (err) {
      console.log(err);
      old_parent.appendChild(el);
    }
  }



  // --- relative --------------------------------------------------------------
  // TODO - make a grid layout for icons on desktop?

  Cat.layout.Relative = function(el) {
    Cat.layout.Relative.superclass.constructor.call(this, el);
  }

  Y.extend(Cat.layout.Relative, Cat.layout.Layout);

  Cat.layout.Relative.prototype.apply = function(el) {
    el.setStyle('position', 'absolute');
    if (el.getStyle('left')[0] == '-' ) {
      el.setStyle('left', '0');
    }
    if (el.getStyle('top')[0] == '-' ) {
      el.setStyle('top', '0');
    }
  }

  Cat.layout.Relative.prototype.drop = function(on, ev) {
    var el = ev.drag.get('node');
    var old_parent = el.get('parentNode');
    if (el.get('parentNode') != on.get('node')) {
      ////console.log('setting', ev.drag.nodeXY[0], ev.drag.nodeXY[1]);
      el.setStyle('left', ev.drag.realXY[0]+'px');
      el.setStyle('top', ev.drag.realXY[1]+'px');
      on.get('node').appendChild(el);
      if (old_parent.layout) {
        old_parent.layout.removeChild(el);
      }
    }
    this.apply(el);
    ev.stopPropagation();
  }






  // -- compatability with the old stuff ---------------------------------------

  dcat.layout.flow = Cat.layout.Horizontal;

  dcat.layout.vertical = Cat.layout.Vertical;

  dcat.layout.relative = Cat.layout.Relative;
  
});